﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace SimplexEngine
{
    public class ScreenEffectSystem
    {
        public ScreenEffectSystem()
        {
            if (vertices == null)
            {
                // create vertices
                vertices = new VertexPositionTexture[4];
                vertices[0] = new VertexPositionTexture(new Vector3(-1, 1, 0), new Vector2(0, 0));
                vertices[1] = new VertexPositionTexture(new Vector3(1, 1, 0), new Vector2(1, 0));
                vertices[2] = new VertexPositionTexture(new Vector3(-1, -1, 0), new Vector2(0, 1));
                vertices[3] = new VertexPositionTexture(new Vector3(1, -1, 0), new Vector2(1, 1));
            }
        }

        /// <summary>
        /// push a material to post process
        /// </summary>
        /// <param name="material">material to push</param>
        public void PushMaterial(Material material)
        {
            materials.Add(material);
        }

        /// <summary>
        /// pop a material form post process
        /// </summary>
        /// <returns></returns>
        public Material PopMaterial()
        {
            // have material?
            if (materials.Count == 0)
                return null;

            // get last material
            Material material = materials.Last();
            // remove last
            materials.RemoveAt(materials.Count - 1);
            return material;
        }

        /// <summary>
        /// clear post process
        /// </summary>
        public void Clear()
        {
            materials.Clear();
        }

        /// <summary>
        /// apply post process
        /// </summary>
        public void Apply(GameTime game_time, Int64 frame_number)
        {
            foreach (Material material in materials)
                if (material.Effect != null)
                    PostMaterial(game_time, frame_number, material);
        }

        internal void PostMaterial(GameTime game_time, Int64 frame_number, Material material)
        {
            // fill parameters
            material.ApplyParameters(game_time, frame_number);
            material.Effect.Begin();

            foreach (EffectPass effect_pass in material.Effect.CurrentTechnique.Passes)
            {
                effect_pass.Begin();
                // set buffer
                Root.Instance.RenderSystem.GraphicsDevice.VertexDeclaration = new VertexDeclaration(Root.Instance.RenderSystem.GraphicsDevice, VertexPositionTexture.VertexElements);
                Root.Instance.RenderSystem.GraphicsDevice.DrawUserPrimitives<VertexPositionTexture>(PrimitiveType.TriangleStrip, vertices, 0, 2);
                effect_pass.End();
            }
            material.Effect.End();
        }

        // vectex
        static protected VertexPositionTexture[] vertices = null;
        // material list
        protected List<Material> materials = new List<Material>();
    }
}
